package etnorservice.etnor_service.service;


import etnorservice.etnor_service.config.DeployWebSocketHandler;
import etnorservice.etnor_service.domain.DeployConfig;

import etnorservice.etnor_service.domain.dto.WebSocketMessage;
import etnorservice.etnor_service.emus.DeployStep;
import etnorservice.etnor_service.utils.GitUtils;
import etnorservice.etnor_service.utils.ShellUtils;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service
@RequiredArgsConstructor
public class DeployService {

    private final GitService gitService;
    private final DeployWebSocketHandler webSocketHandler;

    public String startDeploy(DeployConfig config) {
        String deployId = UUID.randomUUID().toString();

        CompletableFuture.runAsync(() -> {
            try {
                // 执行部署步骤
                executeGitStep(deployId, config);
                executeDependencyStep(deployId, config);
                executeBuildStep(deployId, config);
                executeDeployStep(deployId, config);

                sendMessage(deployId, DeployStep.DEPLOY, "部署完成");
            } catch (Exception e) {
                log.error("部署失败", e);
                sendMessage(deployId, DeployStep.DEPLOY, "部署失败: " + e.getMessage());
            }
        });

        return deployId;
    }

    private void executeGitStep(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.GIT, "开始拉取代码...");
        updateProgress(deployId, DeployStep.GIT, 0);

        // 后端代码
        gitService.cloneOrPull(
                config.getBackend().getRepo(),
                config.getBackend().getBranch(),
                config.getBackend().getPath(),
                config.getBackend().getAuth()
        );
        updateProgress(deployId, DeployStep.GIT, 50);

        // 前端代码
        gitService.cloneOrPull(
                config.getFrontend().getRepo(),
                config.getFrontend().getBranch(),
                config.getFrontend().getPath(),
                config.getFrontend().getAuth()
        );
        updateProgress(deployId, DeployStep.GIT, 100);
    }

    private void executeDependencyStep(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.DEPENDENCY, "开始安装依赖...");
        updateProgress(deployId, DeployStep.DEPENDENCY, 0);

        // 后端依赖
        executeCommand(deployId, DeployStep.DEPENDENCY,
                "mvn clean install -DskipTests",
                config.getBackend().getPath());
        updateProgress(deployId, DeployStep.DEPENDENCY, 50);

        // 前端依赖
        executeCommand(deployId, DeployStep.DEPENDENCY,
                "npm install",
                config.getFrontend().getPath());
        updateProgress(deployId, DeployStep.DEPENDENCY, 100);
    }

    private void executeBuildStep(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.BUILD, "开始构建...");
        updateProgress(deployId, DeployStep.BUILD, 0);

        // 后端构建
        executeCommand(deployId, DeployStep.BUILD,
                "mvn package -DskipTests",
                config.getBackend().getPath());
        updateProgress(deployId, DeployStep.BUILD, 50);

        // 前端构建
        executeCommand(deployId, DeployStep.BUILD,
                "npm run build",
                config.getFrontend().getPath());
        updateProgress(deployId, DeployStep.BUILD, 100);
    }

    private void executeDeployStep(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.DEPLOY, "开始部署服务...");
        updateProgress(deployId, DeployStep.DEPLOY, 0);

        if (config.getOptions().isBackupBefore()) {
            backupCurrentVersion(deployId, config);
        }

        // 部署后端
        deployBackend(deployId, config);
        updateProgress(deployId, DeployStep.DEPLOY, 50);

        // 部署前端
        deployFrontend(deployId, config);
        updateProgress(deployId, DeployStep.DEPLOY, 75);

        if (config.getOptions().isAutoRestart()) {
            restartServices(deployId, config);
        }

        updateProgress(deployId, DeployStep.DEPLOY, 100);
    }

    private void backupCurrentVersion(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.DEPLOY, "备份当前版本...");
        // 实现备份逻辑
    }

    private void deployBackend(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.DEPLOY, "部署后端服务...");
        // 实现后端部署逻辑
    }

    private void deployFrontend(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.DEPLOY, "部署前端服务...");
        // 实现前端部署逻辑
    }

    private void restartServices(String deployId, DeployConfig config) {
        sendMessage(deployId, DeployStep.DEPLOY, "重启服务...");
        // 实现服务重启逻辑
    }

    private void executeCommand(String deployId, DeployStep step, String command, String workDir) {
        try {
            ShellUtils.executeAsync(command, workDir,
                    output -> sendMessage(deployId, step, output))
                    .get(); // 等待命令执行完成
        } catch (Exception e) {
            throw new RuntimeException("执行命令失败: " + command, e);
        }
    }

    private void sendMessage(String deployId, DeployStep step, String message) {
        webSocketHandler.sendMessage(deployId, WebSocketMessage.log(step, message));
    }

    private void updateProgress(String deployId, DeployStep step, int progress) {
        webSocketHandler.sendMessage(deployId, WebSocketMessage.progress(step, progress));
    }
}